home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / xvisrc.zip / EX_CMDS1.C < prev    next >
C/C++ Source or Header  |  1992-07-28  |  19KB  |  860 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)ex_cmds1.c    2.1 (Chris & John Downey) 7/29/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     ex_cmds1.c
  14. * module function:
  15.     File, window and buffer-related command functions
  16.     for ex (colon) commands.
  17. * history:
  18.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  19.     Originally by Tim Thompson (twitch!tjt)
  20.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  21.     Heavily modified by Chris & John Downey
  22.  
  23. ***/
  24.  
  25. #include "xvi.h"
  26.  
  27. #ifdef    MEGAMAX
  28. overlay "ex_cmds1"
  29. #endif
  30.  
  31. static    char    **files;    /* list of input files */
  32. static    int    numfiles;    /* number of input files */
  33. static    int    curfile;    /* number of the current file */
  34.  
  35. char        *altfilename;
  36. static    long    altfileline;
  37.  
  38. static    char    nowrtmsg[] = "No write since last change (use ! to override)";
  39. static    char    nowrtbufs[] = "Some buffers not written (use ! to override)";
  40.  
  41. static    bool_t    more_files P((void));
  42.  
  43. void
  44. do_quit(window, force)
  45. Xviwin    *window;
  46. bool_t    force;
  47. {
  48.     Xviwin    *wp;
  49.     bool_t    changed;
  50.     bool_t    canexit;
  51.  
  52.     if (force) {
  53.     canexit = TRUE;
  54.     } else {
  55.     /*
  56.      * See if any buffers remain modified and unwritten.
  57.      */
  58.     changed = FALSE;
  59.     wp = window;
  60.     do {
  61.         if (is_modified(wp->w_buffer)) {
  62.         changed = TRUE;
  63.         }
  64.     } while ((wp = next_window(wp)) != window);
  65.  
  66.     if (changed) {
  67.         show_error(window, nowrtbufs);
  68.         canexit = FALSE;
  69.     } else {
  70.         canexit = ! more_files();
  71.     }
  72.     }
  73.  
  74.     if (canexit) {
  75.     sys_exit(0);
  76.     }
  77. }
  78.  
  79. /*
  80.  * Split the current window into two, leaving both windows mapped
  81.  * onto the same buffer.
  82.  */
  83. void
  84. do_split_window(window)
  85. Xviwin    *window;
  86. {
  87.     Xviwin    *newwin;
  88.  
  89.     newwin = split_window(window);
  90.     if (newwin == NULL) {
  91.     show_error(window, "No more windows!");
  92.     return;
  93.     }
  94.  
  95.     map_window_onto_buffer(newwin, window->w_buffer);
  96.  
  97.     /*
  98.      * Update the status line of the old window
  99.      * (since it will have been moved).
  100.      * Also update the window - this will almost certainly
  101.      * have no effect on the screen, but is necessary.
  102.      */
  103.     show_file_info(window);
  104.     update_window(window);
  105.  
  106.     /*
  107.      * Show the new window.
  108.      */
  109.     init_sline(newwin);
  110.     update_window(newwin);
  111.     show_file_info(newwin);
  112.  
  113.     /*
  114.      * Update the global window variable.
  115.      */
  116.     curwin = newwin;
  117. }
  118.  
  119. /*
  120.  * Open a new buffer window, with a possible filename arg.
  121.  *
  122.  * do_buffer() is responsible for updating the screen image for the
  123.  * old window, but not the new one, since we may want to move to a
  124.  * different location in the new buffer (e.g. for a tag search).
  125.  */
  126. bool_t
  127. do_buffer(window, filename)
  128. Xviwin    *window;
  129. char    *filename;
  130. {
  131.     Buffer    *buffer;
  132.     Buffer    *new;
  133.     Xviwin    *newwin;
  134.  
  135.     buffer = window->w_buffer;
  136.  
  137.     if (window->w_nrows < (MINROWS + 1) * 2) {
  138.     show_error(window, "Not enough room!");
  139.     return(FALSE);
  140.     }
  141.  
  142.     new = new_buffer();
  143.     if (new == NULL) {
  144.     show_error(window, "No more buffers!");
  145.     return(FALSE);
  146.     }
  147.     newwin = split_window(window);
  148.     if (newwin == NULL) {
  149.     free_buffer(new);
  150.     show_error(window, "No more windows!");
  151.     return(FALSE);
  152.     }
  153.  
  154.     map_window_onto_buffer(newwin, new);
  155.  
  156.     /*
  157.      * Update the status lines of each buffer.
  158.      *
  159.      * Even if (echo & e_SHOWINFO) is turned off, show_file_info()
  160.      * will always call update_sline(), which is what we really
  161.      * need here.
  162.      *
  163.      * Note that we don't need to call move_window_to_cursor() for
  164.      * the old window until it becomes the current window again.
  165.      */
  166.     show_file_info(window);
  167.     init_sline(newwin);
  168.  
  169.     if (filename != NULL) {
  170.     (void) do_edit(newwin, FALSE, filename);
  171.     } else {
  172.     new->b_filename = new->b_tempfname = NULL;
  173.     show_file_info(newwin);
  174.     }
  175.  
  176.     update_window(window);
  177.  
  178.     /*
  179.      * The current buffer (a global variable) has
  180.      * to be updated here. No way around this.
  181.      */
  182.     curbuf = new;
  183.     curwin = newwin;
  184.  
  185.     return(TRUE);
  186. }
  187.  
  188. /*
  189.  * "close" (the current window).
  190.  */
  191. void
  192. do_close_window(win, force)
  193. Xviwin    *win;
  194. bool_t    force;
  195. {
  196.     Buffer    *buffer;
  197.     Xviwin    *best;
  198.  
  199.     buffer = win->w_buffer;
  200.  
  201.     if (is_modified(buffer) && !force && buffer->b_nwindows < 2) {
  202.     /*
  203.      * Don't close a modified buffer.
  204.      */
  205.     show_error(win, nowrtmsg);
  206.     } else if (next_window(win) != win || !more_files()) {
  207.     Xviwin    *w;
  208.  
  209.     /*
  210.      * We can close this window if:
  211.      *
  212.      * (
  213.      *    the buffer has not been modified
  214.      *  or    they are forcing the close
  215.      *  or    there are other windows onto this buffer
  216.      * )
  217.      * AND
  218.      * (
  219.      *    there are other windows still open
  220.      *  or    there are no more files to be edited
  221.      * )
  222.      */
  223.  
  224.     /*
  225.      * Find an adjacent window to take up the screen
  226.      * space used by the one being closed.
  227.      */
  228.     best = NULL;
  229.     for (w = next_window(win); w != win; w = next_window(w)) {
  230.  
  231.         if (w->w_cmdline + 1 == win->w_winpos ||
  232.         w->w_winpos - 1 == win->w_cmdline ||
  233.         w->w_nrows == 0) {
  234.  
  235.         /*
  236.          * We have found an adjacent window;
  237.          * if it is the first such, or if
  238.          * it is smaller than the previous
  239.          * best, it is now the new best.
  240.          */
  241.         if (best == NULL || w->w_nrows < best->w_nrows) {
  242.             best = w;
  243.         }
  244.         }
  245.     }
  246.  
  247.     if (best == NULL) {
  248.         sys_exit(0);
  249.     }
  250.  
  251.     if (buffer->b_nwindows == 1 && buffer->b_filename != NULL) {
  252.         /*
  253.          * Before we free the buffer, save its filename.
  254.          */
  255.         if (altfilename != NULL) {
  256.         free(altfilename);
  257.         }
  258.         altfilename = buffer->b_filename;
  259.         buffer->b_filename = NULL;
  260.         altfileline = lineno(buffer,
  261.             win->w_cursor->p_line);
  262.     }
  263.  
  264.     /*
  265.      * Now "best" points  to the smallest adjacent window;
  266.      * amalgamate the spaces used.
  267.      */
  268.     if (best->w_winpos > win->w_winpos) {
  269.         best->w_winpos = win->w_winpos;
  270.     }
  271.     best->w_nrows += win->w_nrows;
  272.     best->w_cmdline = best->w_winpos + best->w_nrows - 1;
  273.     free_window(win);
  274.  
  275.     if (buffer->b_nwindows == 0) {
  276.         free_buffer(buffer);
  277.     }
  278.  
  279.     /*
  280.      * Have to update the globals "curbuf" and "curwin" here.
  281.      */
  282.     curwin = best;
  283.     curbuf = best->w_buffer;
  284.     {
  285.         unsigned    savecho;
  286.  
  287.         savecho = echo;
  288.         /*
  289.          * Adjust position of new current window
  290.          * within buffer before updating it, to avoid
  291.          * wasting screen output - but don't do any
  292.          * scrolling at this stage because the old
  293.          * window is still on the screen.
  294.          */
  295.         echo &= ~(e_CHARUPDATE | e_SHOWINFO | e_SCROLL);
  296.         move_window_to_cursor(curwin);
  297.         echo = savecho;
  298.  
  299.     }
  300.     update_window(curwin);
  301.     show_file_info(curwin);
  302.     }
  303. }
  304.  
  305. /*
  306.  * Close current window.
  307.  *
  308.  * If it is the last window onto the buffer, also close the buffer.
  309.  *
  310.  * If the buffer has been modified, we must write it out before closing it.
  311.  */
  312. void
  313. do_xit(window)
  314. Xviwin    *window;
  315. {
  316.     Buffer    *buffer;
  317.  
  318.     buffer = window->w_buffer;
  319.  
  320.     if (is_modified(buffer) && buffer->b_nwindows < 2) {
  321.     if (buffer->b_filename != NULL) {
  322.         if (!writeit(window, buffer->b_filename,
  323.                 (Line *) NULL, (Line *) NULL, FALSE)) {
  324.         return;
  325.         }
  326.     } else {
  327.         show_error(window, "No output file");
  328.         return;
  329.     }
  330.     }
  331.  
  332.     do_close_window(window, FALSE);
  333. }
  334.  
  335. /*
  336.  * Edit the given filename in the given buffer,
  337.  * replacing any current contents.  Note that the
  338.  * screen is not updated, since there are routines
  339.  * which use this function before moving the cursor
  340.  * to a different position in the file.
  341.  *
  342.  * Returns TRUE for success, FALSE for failure.
  343.  */
  344. bool_t
  345. do_edit(window, force, arg)
  346. Xviwin    *window;
  347. bool_t    force;
  348. char    *arg;
  349. {
  350.     long    line = 1;        /* line # to go to in new file */
  351.     long    nlines;            /* no of lines read from file */
  352.     Line    *head;            /* start of list of lines */
  353.     Line    *tail;            /* last element of list of lines */
  354.     bool_t    readonly;        /* true if cannot write file */
  355.     Buffer    *buffer;
  356.     Xviwin    *wp;
  357.  
  358.     buffer = window->w_buffer;
  359.  
  360.     if (!force && is_modified(buffer)) {
  361.     show_error(window, nowrtmsg);
  362.     return(FALSE);
  363.     }
  364.  
  365.     if (arg == NULL || arg[0] == '\0') {
  366.     /*
  367.      * No filename specified; we must already have one.
  368.      */
  369.     if (buffer->b_filename == NULL) {
  370.         show_error(window, "No filename");
  371.         return(FALSE);
  372.     }
  373.     } else /* arg != NULL */ {
  374.     /*
  375.      * Filename specified.
  376.      */
  377.  
  378.     /*
  379.      * First detect a ":e" on the cur